package org.wattdepot.cli.command;

import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.cli.processor.CommandLineInterface;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * ListTotalGenerated class returns the total amount of carbon (or energy) generated, in Watts, by a
 * specific source for the given day, within a given interval in minutes. This class extends
 * CommandLineInterface to have access to the WattDepotClient and implements WattDepotCliCommand
 * interface to ensure this class does a specific command.
 * 
 * @author Edward Meyer, Bao Huy Ung
 * 
 */
public class TotalGenerated extends CommandLineInterface implements WattDepotCliCommand {

  /**
   * Creates a ListTotalGenerated object to return the total amount of carbon (or energy) generated,
   * in Watts, by a specific source for the given day, within a given interval in minutes.
   * 
   */
  public TotalGenerated() {
    // Empty constructor.
  }

  /**
   * Returns the total amount of carbon (or energy) generated, in Watts, by a specific source for
   * the given day, within a given interval in minutes.
   * 
   * @param args Is a list of all the arguments entered by the user.
   * @return The amount of carbon/energy generated on a given day, or an error message.
   */
  public String doCommand(List<String> args) {
    if (args.size() != 8) {
      return "Error: Incorrect number of arguments were entered. Expected 8, instead "
          + args.size() + " were entered.";
    }
    // Check if proper keywords were used when entering the command.
    if (!args.get(4).equalsIgnoreCase("day")) {
      return "Error: Keyword \"day\" was mistyped as \"" + args.get(4) + "\".";
    }
    if (!args.get(6).equalsIgnoreCase("sampling-interval")) {
      return "Error: Keyword \"sampling-interval\" was mistyped as \"" + args.get(6) + "\".";
    }
    if (!args.get(2).equalsIgnoreCase("generated")) {
      return "Error: Keyword \"generated\" was mistyped as \"" + args.get(2) + "\".";
    }

    XMLGregorianCalendar timeStamp = null;
    XMLGregorianCalendar endStamp = null;
    String inputStamp = args.get(5);
    String inputSourceName = args.get(3);
    Source inputSource = null;
    Integer inputMinutes = null;

    try {
      inputMinutes = Integer.parseInt(args.get(7));
    }
    catch (NumberFormatException e) {
      return "Error: Sample-interval was not an integer.";
    }

    if (inputMinutes < 1) {
      return "Error: Sampling-interval must be an integer 1 or greater.";
    }

    // Check if a valid source was entered.
    inputSource = isValidSource(inputSourceName);
    if (inputSource == null) {
      return "\"" + inputSourceName + "\" is not a valid source.";
    }

    // Check if a valid timestamp was entered.
    timeStamp = isValidTimestamp(inputStamp);
    if (timeStamp == null) {
      return "Timestamp: \"" + inputStamp + "\" cannot be parsed into a timestamp.";
    }

    // Calculate the ending timestamp.
    endStamp = Tstamp.incrementDays(timeStamp, 1);
    // Decrease by 1 second since endStamp will dip into the next day.
    endStamp = Tstamp.incrementSeconds(endStamp, -1);

    try {
      if (args.get(1).equals("carbon")) {
        Double carbonGenerated =
            client.getCarbonEmitted(inputSourceName, timeStamp, endStamp, inputMinutes);
        return carbonGenerated.toString();
      }
      else if (args.get(1).equals("energy")) {
        Double energyGenerated =
            client.getEnergyGenerated(inputSourceName, timeStamp, endStamp, inputMinutes);
        return energyGenerated.toString();
      }
      else {
        return "Invalid input in {carbon|energy} argument. Incorrect input: \"" + args.get(1)
            + "\"";
      }
    }
    // Catch block if the timestamp yields no data for the given timestamp.
    catch (ResourceNotFoundException r) {
      return "Source: \"" + inputSourceName + "\" contains no " + args.get(1) + " generated data "
          + "on: \"" + inputStamp + "\"";
    }
    catch (BadXmlException b) {
      return "Source: \"" + inputSourceName + "\" contains no " + args.get(1) + " generated data "
          + "on: \"" + inputStamp + "\"";
    }
    // If an unknown error occurred not already caught.
    // Should not happen under normal circumstances.
    catch (Exception e) {
      return "An error occurred when retrieving \"" + args.get(1) + "\" data from server.";
    }

  }

}